package com.yyfax.pay.third.facade.fuioudeposit;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.yyfax.framework.common.Log;
import com.yyfax.pay.common.exception.PayExceptionCode;
import com.yyfax.pay.common.model.vo.PayRspCodeVO;
import com.yyfax.pay.depository.domain.FuiouFrozen;
import com.yyfax.pay.depository.domain.FuiouFrozenAppropriate;
import com.yyfax.pay.depository.domain.FuiouFrozenToFrozen;
import com.yyfax.pay.depository.domain.FuiouFrozenTransfer;
import com.yyfax.pay.depository.domain.FuiouTransferMerchantUser;
import com.yyfax.pay.depository.domain.FuiouTransferUserUser;
import com.yyfax.pay.depository.domain.FuiouUnfrozen;
import com.yyfax.pay.depository.vo.AppropriateFrozenVO;
import com.yyfax.pay.depository.vo.FrozenToFrozenVO;
import com.yyfax.pay.depository.vo.FrozenVO;
import com.yyfax.pay.depository.vo.FuiouResponseVO;
import com.yyfax.pay.depository.vo.TransferFrozenVO;
import com.yyfax.pay.depository.vo.TransferVO;
import com.yyfax.pay.depository.vo.UnfrozenVO;
import com.yyfax.pay.third.model.to.fuioudeposit.FuiouDepositConfigExt;
import com.yyfax.pay.third.model.to.fuioudeposit.xml.BasePlain;
import com.yyfax.pay.third.model.to.fuioudeposit.xml.RootXMLRsp;
import com.yyfax.pay.vo.depository.TradeRsp;

/**
 * 富友存管交易服务
 * 
 * @author heizq
 * @date 2017-10-03 14:36:42
 * @since v1.0.0
 */
@Service
public class FuiouDepositTradeService {

	Logger logger = LoggerFactory.getLogger(getClass());

	@Resource
	private FuiouSignService fuiouSignService;

	@Resource
	private FuiouDepositService fuiouDepositService;

	/**
	 * 冻结
	 * 
	 * @author heizq
	 * @date 2017-10-03 14:37:05
	 * @since v1.0.0
	 * @param domain
	 * @return
	 */
	public TradeRsp frozen(FuiouFrozen domain) {
		String op = "FuiouDepositTradeService.frozen";
		try {
			FuiouDepositConfigExt extInfo = fuiouSignService.getFuiouDepositConfig(domain.getMerchantCode());

			// 构建请求参数，发请求
			FrozenVO vo = buildFrozenReqParams(domain, extInfo);
			FuiouResponseVO rsp = fuiouDepositService.postForResponseVO(vo, extInfo.getFrozenUrl(), domain.getMerchantCode());

			return parserResult(rsp, domain.getBusiId());
		} catch (Exception e) {
			logger.error(Log.op(op).msg("【富友存管-冻结】发送请求失败！").kv("busiId", domain.getBusiId()).toString());
			return new TradeRsp(PayExceptionCode.ERROR_PAY_FAIL.getCode(), PayExceptionCode.ERROR_PAY_FAIL.getDesc(), domain.getBusiId());
		}
	}

	/**
	 * 冻结到冻结
	 * 
	 * @author heizq
	 * @date 2017-10-03 16:59:02
	 * @since v1.0.0
	 * @param domain
	 * @return
	 */
	public TradeRsp frozenToFrozen(FuiouFrozenToFrozen domain) {
		String op = "FuiouDepositTradeService.frozenToFrozen";
		try {
			FuiouDepositConfigExt extInfo = fuiouSignService.getFuiouDepositConfig(domain.getMerchantCode());

			// 构建请求参数，发请求
			FrozenToFrozenVO vo = buildFrozenToFrozenReqParams(domain, extInfo);
			FuiouResponseVO rsp = fuiouDepositService.postForResponseVO(vo, extInfo.getFrozen2FrozenUrl(), domain.getMerchantCode());

			return parserResult(rsp, domain.getBusiId());
		} catch (Exception e) {
			logger.error(Log.op(op).msg("【富友存管-冻结到冻结】发送请求失败！").kv("busiId", domain.getBusiId()).toString());
			return new TradeRsp(PayExceptionCode.ERROR_PAY_FAIL.getCode(), PayExceptionCode.ERROR_PAY_FAIL.getDesc(), domain.getBusiId());
		}
	}

	/**
	 * 转账预冻结
	 * 
	 * @author heizq
	 * @date 2017-10-03 17:23:20
	 * @since v1.0.0
	 * @param domain
	 * @return
	 */
	public TradeRsp transferFrozen(FuiouFrozenTransfer domain) {
		String op = "FuiouDepositTradeService.transferFrozen";
		try {
			FuiouDepositConfigExt extInfo = fuiouSignService.getFuiouDepositConfig(domain.getMerchantCode());

			// 构建请求参数，发请求
			TransferFrozenVO vo = buildTransferFrozenReqParams(domain, extInfo);
			FuiouResponseVO rsp = fuiouDepositService.postForResponseVO(vo, extInfo.getTransferFrozenUrl(), domain.getMerchantCode());

			return parserResult(rsp, domain.getBusiId());
		} catch (Exception e) {
			logger.error(Log.op(op).msg("【富友存管-转账预冻结】发送请求失败！").kv("busiId", domain.getBusiId()).toString());
			return new TradeRsp(PayExceptionCode.ERROR_PAY_FAIL.getCode(), PayExceptionCode.ERROR_PAY_FAIL.getDesc(), domain.getBusiId());
		}
	}

	/**
	 * 划拨预冻结
	 * 
	 * @author heizq
	 * @date 2017-10-03 17:33:22
	 * @since v1.0.0
	 * @param domain
	 * @return
	 */
	public TradeRsp appropriateFrozen(FuiouFrozenAppropriate domain) {
		String op = "FuiouDepositTradeService.appropriateFrozen";
		try {
			FuiouDepositConfigExt extInfo = fuiouSignService.getFuiouDepositConfig(domain.getMerchantCode());

			// 构建请求参数，发请求
			AppropriateFrozenVO vo = buildAppropriateFrozenReqParams(domain, extInfo);
			FuiouResponseVO rsp = fuiouDepositService.postForResponseVO(vo, extInfo.getAppropriateFrozenUrl(), domain.getMerchantCode());

			return parserResult(rsp, domain.getBusiId());
		} catch (Exception e) {
			logger.error(Log.op(op).msg("【富友存管-划拨预冻结】发送请求失败！").kv("busiId", domain.getBusiId()).toString());
			return new TradeRsp(PayExceptionCode.ERROR_PAY_FAIL.getCode(), PayExceptionCode.ERROR_PAY_FAIL.getDesc(), domain.getBusiId());
		}
	}

	/**
	 * 解冻
	 * 
	 * @author heizq
	 * @date 2017-10-04 08:38:49
	 * @since v1.0.0
	 * @param domain
	 * @return
	 */
	public TradeRsp unfrozen(FuiouUnfrozen domain) {
		String op = "FuiouDepositTradeService.unfrozen";
		try {
			FuiouDepositConfigExt extInfo = fuiouSignService.getFuiouDepositConfig(domain.getMerchantCode());

			// 构建请求参数，发请求
			UnfrozenVO vo = buildUnfrozenReqParams(domain, extInfo);
			FuiouResponseVO rsp = fuiouDepositService.postForResponseVO(vo, extInfo.getUnrozenUrl(), domain.getMerchantCode());

			return parserResult(rsp, domain.getBusiId());
		} catch (Exception e) {
			logger.error(Log.op(op).msg("【富友存管-解冻】发送请求失败！").kv("busiId", domain.getBusiId()).toString());
			return new TradeRsp(PayExceptionCode.ERROR_PAY_FAIL.getCode(), PayExceptionCode.ERROR_PAY_FAIL.getDesc(), domain.getBusiId());
		}
	}

	/**
	 * 构建冻结请求参数
	 * 
	 * @author heizq
	 * @date 2017-09-02 13:30:50
	 * @since v1.0.0
	 * @param domain
	 * @param extInfo
	 * @return
	 */
	private FrozenVO buildFrozenReqParams(FuiouFrozen domain, FuiouDepositConfigExt extInfo) {
		FrozenVO vo = new FrozenVO();
		vo.setVersion(extInfo.getVersion());
		vo.setMerchantId(extInfo.getMerchantId());
		vo.setBusiId(domain.getBusiId());
		vo.setAccountNo(domain.getAccountNo());
		vo.setAmount(domain.getAmount() + "");
		vo.setRemark(domain.getRemark());
		vo.setSignature(fuiouSignService.getSign(domain.getMerchantCode(), vo));
		return vo;
	}

	/**
	 * 构建冻结到冻结请求参数
	 * 
	 * @author heizq
	 * @date 2017-09-02 13:30:50
	 * @since v1.0.0
	 * @param domain
	 * @param extInfo
	 * @return
	 */
	private FrozenToFrozenVO buildFrozenToFrozenReqParams(FuiouFrozenToFrozen domain, FuiouDepositConfigExt extInfo) {
		FrozenToFrozenVO vo = new FrozenToFrozenVO();
		vo.setVersion(extInfo.getVersion());
		vo.setMerchantId(extInfo.getMerchantId());
		vo.setBusiId(domain.getBusiId());
		vo.setOutAccountNo(domain.getOutAccountNo());
		vo.setInAccountNo(domain.getInAccountNo());
		vo.setAmount(domain.getAmount() + "");
		vo.setRemark(domain.getRemark());
		vo.setSignature(fuiouSignService.getSign(domain.getMerchantCode(), vo));
		return vo;
	}

	/**
	 * 构建转账预冻结请求参数
	 * 
	 * @author heizq
	 * @date 2017-09-02 13:30:50
	 * @since v1.0.0
	 * @param domain
	 * @param extInfo
	 * @return
	 */
	private TransferFrozenVO buildTransferFrozenReqParams(FuiouFrozenTransfer domain, FuiouDepositConfigExt extInfo) {
		TransferFrozenVO vo = new TransferFrozenVO();
		vo.setVersion(extInfo.getVersion());
		vo.setMerchantId(extInfo.getMerchantId());
		vo.setBusiId(domain.getBusiId());
		vo.setOutAccountNo(domain.getOutAccountNo());
		vo.setInAccountNo(domain.getInAccountNo());
		vo.setAmount(domain.getAmount() + "");
		vo.setRemark(domain.getRemark());
		vo.setSignature(fuiouSignService.getSign(domain.getMerchantCode(), vo));
		return vo;
	}

	/**
	 * 构建划拨预冻结请求参数
	 * 
	 * @author heizq
	 * @date 2017-09-02 13:30:50
	 * @since v1.0.0
	 * @param domain
	 * @param extInfo
	 * @return
	 */
	private AppropriateFrozenVO buildAppropriateFrozenReqParams(FuiouFrozenAppropriate domain, FuiouDepositConfigExt extInfo) {
		AppropriateFrozenVO vo = new AppropriateFrozenVO();
		vo.setVersion(extInfo.getVersion());
		vo.setMerchantId(extInfo.getMerchantId());
		vo.setBusiId(domain.getBusiId());
		vo.setOutAccountNo(domain.getOutAccountNo());
		vo.setInAccountNo(domain.getInAccountNo());
		vo.setAmount(domain.getAmount() + "");
		vo.setRemark(domain.getRemark());
		vo.setSignature(fuiouSignService.getSign(domain.getMerchantCode(), vo));
		return vo;
	}

	/**
	 * 构建解冻请求参数
	 * 
	 * @author heizq
	 * @date 2017-09-02 13:30:50
	 * @since v1.0.0
	 * @param domain
	 * @param extInfo
	 * @return
	 */
	private UnfrozenVO buildUnfrozenReqParams(FuiouUnfrozen domain, FuiouDepositConfigExt extInfo) {
		UnfrozenVO vo = new UnfrozenVO();
		vo.setVersion(extInfo.getVersion());
		vo.setMerchantId(extInfo.getMerchantId());
		vo.setBusiId(domain.getBusiId());
		vo.setAccountNo(domain.getAccountNo());
		vo.setAmount(domain.getAmount() + "");
		vo.setRemark(domain.getRemark());
		vo.setSignature(fuiouSignService.getSign(domain.getMerchantCode(), vo));
		return vo;
	}

	/**
	 * 解析响应结果
	 * 
	 * @author heizq
	 * @date 2017-09-04 11:38:48
	 * @since v1.0.0
	 * @param rsp
	 * @param busiId 业务主键
	 */
	private TradeRsp parserResult(FuiouResponseVO rsp, String busiId) {
		final String op = "FuiouDepositTradeService.parserResult";

		if (FuiouResponseVO.TIMEOUT.equals(rsp.getResult())) {
			return new TradeRsp(PayExceptionCode.WARN_REQ_TIME_OUT.getCode(), PayExceptionCode.WARN_REQ_TIME_OUT.getDesc(), busiId);
		}

		if (FuiouResponseVO.INVALID_DATA.equals(rsp.getResult())) {
			// 其他异常返回对应匹配后的响应消息
			return new TradeRsp(PayExceptionCode.SYS_ERROR.getCode(), PayExceptionCode.SYS_ERROR.getDesc(), busiId);
		}

		if (FuiouResponseVO.NORMAL.equals(rsp.getResult())) {
			String result = rsp.getContent();
			RootXMLRsp<BasePlain> fuiouRsp = (RootXMLRsp<BasePlain>) RootXMLRsp.fromXml(result, BasePlain.class);
			PayRspCodeVO codeExp = fuiouDepositService.converToPayRspCode(fuiouRsp.getPlain().getRspCode());
			if (!PayExceptionCode.SUCCESS.isCode(codeExp.getCode())) {
				// 第三方返回超时
				if (PayExceptionCode.WARN_REQ_TIME_OUT.isCode(codeExp.getCode())) {
					return new TradeRsp(PayExceptionCode.WARN_REQ_TIME_OUT.getCode(), PayExceptionCode.WARN_REQ_TIME_OUT.getDesc(), busiId);
				} else {
					// 其他异常返回对应匹配后的响应消息
					return new TradeRsp(codeExp.getCode(), codeExp.getDesc(), busiId);
				}
			}
			// 成功
			return new TradeRsp(PayExceptionCode.SUCCESS.getCode(), PayExceptionCode.SUCCESS.getDesc(), busiId);
		}

		logger.info(Log.op(op).msg("【富友存管-冻结】冻结失败，返回的结果不是预期到的").kv("result", rsp.toString()).toString());
		return new TradeRsp(PayExceptionCode.ERROR_PAY_FAIL.getCode(), PayExceptionCode.ERROR_PAY_FAIL.getDesc(), busiId);
	}

	/**
	 * 转账(商户与个人之间)
	 *
	 * @author yejc
	 * @date 2017-10-09
	 * @since v2.0.0
	 * @param domain
	 * @return
	 */
	public PayRspCodeVO transferMerchantAndUser(FuiouTransferMerchantUser domain) {
		String op = "FuiouDepositTradeService.transferMerchantAndUser";
		try {
			FuiouDepositConfigExt extInfo = fuiouSignService.getFuiouDepositConfig(domain.getMerchantCode());
			// 构建请求参数
			TransferVO transferVO = buildTransferReqParams(extInfo, domain.getMerchantCode(), domain.getBusiId(), domain.getOutAccountNo(),
					domain.getInAccountNo(), domain.getAmount().toString(), domain.getContractNo(), domain.getRemark());

			// 请求存管系统
			FuiouResponseVO resp = fuiouDepositService.postForResponseVO(transferVO, extInfo.getTransferMerchantAndUser(), domain.getMerchantCode());

			return fuiouDepositService.parseResponse(resp);
		} catch (Exception e) {
			logger.error(Log.op(op).msg("【富友存管-转账(商户与个人之间)】发送请求失败！").kv("busiId", domain.getBusiId()).toString(), e);
			return PayRspCodeVO.newInstance(PayExceptionCode.ERROR_PAY_FAIL.getCode(), PayExceptionCode.ERROR_PAY_FAIL.getDesc());
		}
	}

	/**
	 * 划拨(个人与个人之间)
	 *
	 * @author yejc
	 * @date 2017-10-09
	 * @since v2.0.0
	 * @param domain
	 * @return
	 */
	public PayRspCodeVO transferUserAndUser(FuiouTransferUserUser domain) {
		String op = "FuiouDepositTradeService.transferUserAndUser";
		try {
			FuiouDepositConfigExt extInfo = fuiouSignService.getFuiouDepositConfig(domain.getMerchantCode());
			// 构建请求参数
			TransferVO transferVO = buildTransferReqParams(extInfo, domain.getMerchantCode(), domain.getBusiId(), domain.getOutAccountNo(),
					domain.getInAccountNo(), domain.getAmount().toString(), domain.getContractNo(), domain.getRemark());

			// 请求存管系统
			FuiouResponseVO resp = fuiouDepositService.postForResponseVO(transferVO, extInfo.getTransferUserAndUser(), domain.getMerchantCode());

			return fuiouDepositService.parseResponse(resp);
		} catch (Exception e) {
			logger.error(Log.op(op).msg("【富友存管-划拨(个人与个人之间)】发送请求失败！").kv("busiId", domain.getBusiId()).toString(), e);
			return PayRspCodeVO.newInstance(PayExceptionCode.ERROR_PAY_FAIL.getCode(), PayExceptionCode.ERROR_PAY_FAIL.getDesc());
		}
	}

	/**
	 * 封装转账划拨请求参数
	 *
	 * @author yejc
	 * @date 2017-10-09
	 * @since v2.0.0
	 *  @param extInfo
	 * @param merchantCode
	 * @param busiId
	 * @param outAccountNo
	 * @param inAccountNo
	 * @param amount
	 * @param contractNo
	 * @param remark @return
	 */
	private TransferVO buildTransferReqParams(FuiouDepositConfigExt extInfo, String merchantCode, String busiId, String outAccountNo, String inAccountNo, String amount, String contractNo, String remark) {
		TransferVO vo = new TransferVO();
		vo.setVersion(extInfo.getVersion());
		vo.setMerchantId(extInfo.getMerchantId());
		vo.setBusiId(busiId);
		vo.setOutAccountNo(outAccountNo);
		vo.setInAccountNo(inAccountNo);
		vo.setAmount(amount);
		vo.setContractNo(contractNo);
		vo.setRemark(remark);
		vo.setSignature(fuiouSignService.getSign(merchantCode, vo));

		return vo;
	}
}
